<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>使用装饰器实现自动发布事件</title>
</head>
<body>
    <h1>使用装饰器实现自动发布事件</h1>

    <script>
        // 事件中心
        class EventEmitter {
            constructor() {
                this._events = new Map();
            }

            on(type, handler) {
                const handlers = this._events.get(type) || [];
                handlers.push(handler);
                this._events.set(type, handlers);
            }

            emit(type, ...args) {
                const handlers = this._events.get(type) || [];
                handlers.forEach(handler => handler.apply(this, args));
            }
        }

        // 发布事件装饰器
        function publish(eventType) {
            return function(target, name, descriptor) {
                const original = descriptor.value;
                
                descriptor.value = function(...args) {
                    const result = original.apply(this, args);
                    if (this.emit) {
                        this.emit(eventType, result);
                    }
                    return result;
                };
                
                return descriptor;
            };
        }

        // 实际应用示例
        class User extends EventEmitter {
            constructor(name) {
                super();
                this.name = name;
            }

            @publish('nameChanged')
            setName(newName) {
                const oldName = this.name;
                this.name = newName;
                return { oldName, newName };
            }

            @publish('profileUpdated')
            updateProfile(data) {
                Object.assign(this, data);
                return data;
            }
        }

        // 使用示例
        const user = new User('张三');

        user.on('nameChanged', ({ oldName, newName }) => {
            console.log(`用户名从 ${oldName} 改为 ${newName}`);
        });

        user.on('profileUpdated', data => {
            console.log('用户资料更新:', data);
        });

        user.setName('李四');
        user.updateProfile({ age: 25, city: '北京' });

        // 更复杂的示例：表单验证
        function validate(rules) {
            return function(target, name, descriptor) {
                const original = descriptor.value;
                
                descriptor.value = function(...args) {
                    const errors = [];
                    Object.entries(rules).forEach(([field, rule]) => {
                        if (!rule.test(this[field])) {
                            errors.push(`${field} 验证失败`);
                        }
                    });
                    
                    if (errors.length > 0) {
                        this.emit('validationError', errors);
                        return false;
                    }
                    
                    const result = original.apply(this, args);
                    this.emit('validated', result);
                    return result;
                };
                
                return descriptor;
            };
        }

        class Form extends EventEmitter {
            constructor() {
                super();
                this.username = '';
                this.email = '';
            }

            @validate({
                username: /^[a-zA-Z0-9]{3,20}$/,
                email: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/
            })
            submit() {
                return {
                    username: this.username,
                    email: this.email
                };
            }
        }
    </script>
</body>
</html> 